#include "CFramework.h"
#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>
#include "resource.h"

CFramework::CFramework(CBaseApp* pGameApp)
{
	g_pGameApp = pGameApp;
	g_pGraphics = new CGraphics();
	g_pTimer = new CTimer();

	g_hInst = NULL;
	g_hWnd = NULL;
}


CFramework::~CFramework(void)
{
}

//--------------------------------------------------------------------------------------
// Register class and create window
//--------------------------------------------------------------------------------------
HRESULT CFramework::InitWindow( char* title, HINSTANCE hInstance, int width, int height, BOOL windowed )
{
    // Register class
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof( WNDCLASSEX );
    wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
    wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
    wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = L"TutorialWindowClass";
    wcex.hIconSm = LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
    if( !RegisterClassEx( &wcex ) )
        return E_FAIL;

    // Create window
    g_hInst = hInstance;
    RECT rc = { 0, 0, 640, 480 };
    AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
    g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 11 Tutorial 1: Direct3D 11 Basics", WS_OVERLAPPEDWINDOW,
                           CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance,
                           NULL );
    if( !g_hWnd )
        return E_FAIL;

    ShowWindow( g_hWnd, SW_SHOW );

	// Initialize Direct3D
	if( g_pGraphics->InitDevice(g_hWnd, FALSE) )
	{
		g_pGraphics->CleanupDevice();
		return 0;
	}

	OnCreateDevice();

    return S_OK;
}


//--------------------------------------------------------------------------------------
// Called every time the application receives a message
//--------------------------------------------------------------------------------------
LRESULT CALLBACK CFramework::WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    PAINTSTRUCT ps;
    HDC hdc;

    switch( message )
    {
        case WM_PAINT:
            hdc = BeginPaint( hWnd, &ps );
            EndPaint( hWnd, &ps );
            break;

        case WM_DESTROY:
            PostQuitMessage( 0 );
            break;

        default:
            return DefWindowProc( hWnd, message, wParam, lParam );
    }

    return 0;
}

void CFramework::OnUpdateFrame()
{
	if ( g_pTimer != NULL )
		g_pTimer->Update();

	if ( g_pGameApp != NULL && g_pGraphics != NULL && g_pTimer != NULL )
	{
		float elapsedTime = g_pTimer->GetElapsedTime();

		//Process Input

		g_pGameApp->OnUpdateFrame( g_pGraphics->GetpImmediateContext(), g_pGraphics->GetpSwapChain(), elapsedTime); //
	}

}

void CFramework::OnRenderFrame()
{
	g_pGameApp->OnRenderFrame( g_pGraphics->GetpImmediateContext(), g_pGraphics->GetpSwapChain(), g_pGraphics->GetpRenderTargetView(), g_pGraphics->GetpDepthStencilView(), g_pTimer->GetElapsedTime());
}

void CFramework::OnCreateDevice()
{
	if ( g_pGameApp != NULL && g_pGraphics != NULL )
	{
		g_pGameApp->OnCreateDevice( g_pGraphics->Getpd3dDevice(), g_pGraphics->GetpImmediateContext(), g_pGraphics->GetpSwapChain() );
	}
}

void CFramework::Pause( BOOL rendering, BOOL timer )
{
	g_renderingPauseCount += rendering ? 1 : -1;
	g_renderingPauseCount = (g_renderingPauseCount < 0) ? 0 : g_renderingPauseCount;

	g_timerPauseCount += timer ? 1 : -1;
	g_timerPauseCount = (g_timerPauseCount < 0) ? 0 : g_timerPauseCount;

	g_renderingPaused = (g_renderingPauseCount > 0);
	g_timerPaused = (g_timerPauseCount > 0);

	if ( g_timerPaused && g_pTimer != NULL )
	{
		g_pTimer->Stop();
	}
	else if ( !g_timerPaused && g_pTimer != NULL )
	{
		g_pTimer->Start();
	}
}

float CFramework::GetFPS()
{
    if ( g_pTimer != NULL )
		return g_pTimer->GetFPS();
    
    return 0.0f;
}

void CFramework::Run()
{
	MSG msg = {0};

	while( WM_QUIT != msg.message )
	{
		if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
		{
			TranslateMessage( &msg );
			DispatchMessage( & msg );
		}
		else
		{
			OnUpdateFrame();
			OnRenderFrame();
		}
	}

	g_pGraphics->CleanupDevice(); // Do SAFE_RELEASE MACRO

}

